home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 048 (1988-02-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 048 (1988-02-15)(Ossowski, Stefan)(DE)(PD).adf / Mandel / source / jiff.c < prev    next >
C/C++ Source or Header  |  1988-01-23  |  22KB  |  907 lines

  1.  
  2. /* JIFF.H */
  3.  
  4. /************ I usually put these in a file called format.h ****/
  5.  
  6.  
  7. #define XMAX 640
  8. #define LOXMAX 320
  9. #define YMAX 200
  10. #define XASPECT 5
  11. #define YASPECT 11
  12.  
  13. /* EA handy make a long from 4 chars macros redone to work with Aztec*/
  14. #define MAKE_ID(a, b, c, d)\
  15. ( ((long)(a)<<24) | ((long)(b)<<16) | ((long)(c)<<8) | (long)(d) )
  16.  
  17. /* These are the IFF types I deal with */
  18. #define FORM MAKE_ID('F', 'O', 'R', 'M')
  19. #define ILBM MAKE_ID('I', 'L', 'B', 'M')
  20. #define BMHD MAKE_ID('B', 'M', 'H', 'D')
  21. #define CMAP MAKE_ID('C', 'M', 'A', 'P')
  22. #define BODY MAKE_ID('B', 'O', 'D', 'Y')
  23.  
  24. /* And these are the IFF types I ignore but don't squawk about */
  25. #define GRAB MAKE_ID('G', 'R', 'A', 'B')
  26. #define DEST MAKE_ID('D', 'E', 'S', 'T')
  27. #define SPRT MAKE_ID('S', 'P', 'R', 'T')
  28. #define CAMG MAKE_ID('C', 'A', 'M', 'G')
  29. #define CRNG MAKE_ID('C', 'R', 'N', 'G')
  30. #define CCRT MAKE_ID('C', 'C', 'R', 'T')
  31.  
  32. #define EVEN(x)    (((x) + 1) & ~1)
  33. #define MANDEL
  34.  
  35. /* Some macros for raster memory allocation ... redefine if you're
  36.    sensible and manage memory locally */
  37.  
  38. #ifndef MANDEL
  39.  
  40.     /* ralloc - raster alloc */
  41. # define ralloc(amount)  (PLANEPTR)AllocMem((long)(amount), MEMF_CHIP)
  42.     /* rfree - raster free */
  43. # define rfree(pt, amount)    FreeMem( (pt), (long)(amount) )
  44.  
  45. #else /* MANDEL */
  46.  
  47. # include <mandel.h>
  48. /*
  49.  * We don't want to allocate a complete raster for the picture, since we
  50.  * already have a screen with a window where we want to have it.
  51.  * Therefore, we allocate some small buffers, which get blitted into
  52.  * our window as soon as they fill up.
  53.  */
  54. # define MAXPLANESIZE    1040L
  55.     /* ralloc - raster alloc */
  56. # define ralloc(amount) (PLANEPTR)AllocMem(MAXPLANESIZE, MEMF_CHIP)
  57.     /* rfree - raster free */
  58. # define rfree(pt, amount)    FreeMem( (pt), MAXPLANESIZE )
  59.  
  60. #endif /* !MANDEL */
  61.  
  62. /* line_bytes = the number of words * 2 (for bytes) a raster line takes up */
  63. #define line_bytes(width)    (((width + 15) >> 3) & ~0x0001)
  64.  
  65. /* psize - plane size in bytes (an even number) of a raster given
  66.    width and height */
  67. #define psize(width, height) ( line_bytes(width)*height)
  68.  
  69. /* The place to throw excess bits */
  70. #define bit_bucket(file, length) fseek(file, (long)EVEN(length), 1)
  71.  
  72.  
  73. union bytes4
  74. {
  75.     char b4_name[4];
  76.     long b4_type;
  77. };
  78.  
  79. struct iff_chunk
  80. {
  81.     union bytes4 iff_type;
  82.     long iff_length;
  83. };
  84.  
  85. struct form_chunk
  86. {
  87.     union bytes4 fc_type; /* == FORM */
  88.     long fc_length;
  89.     union bytes4 fc_subtype;
  90. };
  91.  
  92. #ifndef MANDEL        /* We have this already in Mandel.H */
  93. struct BitMapHeader
  94. {
  95.     UWORD w, h;
  96.     UWORD x, y;
  97.     UBYTE nPlanes;
  98.     UBYTE masking;
  99.     UBYTE compression;
  100.     UBYTE pad1;
  101.     UWORD transparentColor;
  102.     UBYTE xAspect, yAspect;
  103.     WORD pageWidth, pageHeight;
  104. };
  105.  
  106. /* ILBM_info is the structure read_iff returns, and is hopefully all
  107.    you need to deal with out of the iff reader routines below */
  108. struct ILBM_info
  109. {
  110.     struct BitMapHeader header;
  111.     UBYTE cmap[MAXCOL*3];
  112.     struct BitMap bitmap;
  113. };
  114.  
  115. #endif /* !MANDEL */
  116.  
  117. /* I sure wish C function "prototypes" were real and not just ANSI
  118.  * extern struct ILBM_info *read_iff();
  119.  * read_iff( char *filename, short just_colors, int ExtraSize,
  120.  *     APTR ExtraInfo );
  121.  * extern void free_planes();  free_planes( struct BitMap *bitmap);
  122.  * extern int write_iff();
  123.  * write_iff(char *name, unsigned char *colors, struct BitMap *bits,
  124.  *    short xoff, short yoff, short width, short compressed);
  125.  */
  126.  
  127. /* extern char *AllocMem(); */
  128.  
  129.  
  130. /* Anyone know where some useful minterms are defined? */
  131. #define COPY_MINTERM        0x0C0L
  132.  
  133. /***
  134.  
  135.         A meditation for the guru from the Diamond Sutra -
  136.  
  137.         So shall you think of all this fleeting world:
  138.         A star at dawn, a bubble in a stream;
  139.         A flash of lightning in a summer cloud,
  140.         A flickering lamp, a phantom, and a dream.
  141.  
  142. ***/
  143.  
  144.  
  145. /**********************************************************************
  146. *
  147. *            jiff.c   Jim Kent's iff - ilbm  reader
  148. *
  149. * This is the (sortof) short (sortof) simple no-frills IFF reader
  150. * to get something out of DPaint, Images, or the Animator.  It
  151. * works well with the Aztec C compiler.  It should work with Lattice
  152. * but you never know until you try it.  I haven't.
  153. *
  154. * I've included a simple main program.  This is just to make it
  155. * stand alone.  Since amiga screen initializations are massive, all
  156. * it does as is is read it into a BitMap, and then free up the BitMap.
  157. * Should crash it if it's gonna crash though.
  158. *
  159. * The main interface to this is through the routine read_iff(filename).
  160. * This returns a ILBM_info structure-pointer on success, and NULL on
  161. * failure.  It cleans up after itself on failure.
  162. *
  163. * I hope you will find this useful and easy to use.  Please forgive
  164. * my funky indentation style?  Well at least I'm consistent!
  165. * (* Run through the C-Beautifier by Olaf Seibert !! *)
  166. *
  167. * To demonstrate what a nice guy I am even though I'm far from wild
  168. * about the IFF standard I'm placing this in the public domain.  When
  169. * you remove the DEBUG and PARANOID definitions the code is only
  170. * 1536 bytes long.
  171. *
  172. *        -Jim Kent  April 22, 1986
  173. ************************************************************************/
  174.  
  175.  
  176. #include <stdio.h>
  177. #include <exec/types.h>
  178. #include <exec/memory.h>
  179. #include <graphics/gfx.h>
  180. #include <libraries/dos.h>
  181. /* #include "jiff.h"    */
  182.  
  183.  
  184. /* This is an all too common state of software development.  Get rid
  185.    of this define as soon as it runs. */
  186. #undef DEBUG
  187.  
  188. /* This is the normal state of software development.  Seriously undefine
  189.    this to make it shut up about errors and reduce code size half way
  190.    through beta testing... */
  191. #undef PARANOID
  192.  
  193. /* This is nice if you want to use a debugger on the STATIC data and
  194.    routines in this file. Redefine only if you don't need a debugger. */
  195. /* #undef STATIC */
  196. /* #define STATIC */
  197.  
  198. STATIC struct ILBM_info *read_ilbm(), *read_body();
  199.  
  200. /* OK this code is almost re-entrant.  Pass this guy from above to
  201.    make it really re-entrant.  (Why do you need a reentrant ILBM
  202.    reader though??  Maybe for Dale ... )
  203.    Well, look in the IFF specs for instance... [Olaf Seibert, KosmoSoft] */
  204. STATIC struct ILBM_info root_info;  /* static so get initialized to zero */
  205.  
  206.  
  207. #ifdef PARANOID
  208. /* a little paranoid routine that say's where we got before EOF */
  209. STATIC void iff_truncated(where)
  210. int where;
  211. {
  212.     printf("ILBM truncated %d\n", where);
  213.     free_planes(&root_info.bitmap);
  214. }
  215. #endif PARANOID
  216.  
  217.  
  218. struct ILBM_info *read_iff(name, just_colors, ExtraSize, ExtraPointer)
  219. char *name;
  220. short just_colors;
  221. int ExtraSize;
  222. APTR ExtraPointer;
  223. {
  224.     struct ILBM_info *info = &root_info;
  225.     FILE *file;
  226.     struct form_chunk chunk;
  227.  
  228.     if ((file = fopen(name, "r") ) == 0) {
  229. #ifdef PARANOID
  230.         printf("couldn't Open %s to read\n", name);
  231. #endif PARANOID
  232.         return NULL;
  233.     }
  234.  
  235.     if ( fread(&chunk, sizeof(struct form_chunk), 1, file) != 1) {
  236. #ifdef PARANOID
  237.         iff_truncated(0);
  238. #endif PARANOID
  239.         fclose(file);
  240.         return NULL;
  241.     }
  242.  
  243.     if (chunk.fc_type.b4_type != FORM) {
  244. #ifdef PARANOID
  245.         printf("not a FORM - %s\n", name);
  246. #endif PARANOID
  247.         fclose(file);
  248.         return NULL;
  249.     }
  250.  
  251.     if (chunk.fc_subtype.b4_type != ILBM) {
  252. #ifdef PARANOID
  253.         printf("FORM not an ILBM - %s\n", name);
  254. #endif PARANOID
  255.         fclose(file);
  256.         return NULL;
  257.     }
  258.  
  259. #ifdef DEBUG
  260.     printf("FORM %ld ILBM\n", chunk.fc_length);
  261. #endif DEBUG
  262.  
  263.     info = read_ilbm(file, info, chunk.fc_length - sizeof(chunk), just_colors);
  264. #ifdef DEBUG
  265.     printf("info = %lx\n", info);
  266. #endif DEBUG
  267.  
  268. #ifdef MANDEL
  269.     if (info && ExtraSize) {
  270.         /* We may want to read the extra MAND */
  271.         fread(ExtraPointer, 1, ExtraSize, file);
  272.     }
  273. #endif MANDEL
  274.  
  275.     fclose(file);
  276.  
  277.     return info;
  278. }
  279.  
  280. STATIC struct ILBM_info *read_ilbm(file, info, length, just_colors)
  281. FILE *file;
  282. struct ILBM_info *info;
  283. long length;
  284. short just_colors;
  285. {
  286.     struct iff_chunk chunk;
  287.     int i;
  288.     long read_in = 0;
  289.     int got_header = FALSE;  /* To make sure gots the header first */
  290.     int got_cmap = FALSE;    /* Make sure get cmap before "BODY" */
  291.  
  292. /* Make sure the Planes are all NULL so can free up memory easily
  293.    on error abort */
  294.     for (i=0; i<8; i++)
  295.         info->bitmap.Planes[i] = NULL;
  296.  
  297.     while (read_in < length) {
  298.         if (fread(&chunk, sizeof(chunk), 1, file) != 1) {
  299. #ifdef PARANOID
  300.             iff_truncated(1);
  301. #endif PARANOID
  302.             return NULL;
  303.         }
  304.         switch (chunk.iff_type.b4_type) {
  305.         case BMHD:
  306. #ifdef DEBUG
  307.             printf("\tBMHD %ld\n", chunk.iff_length);
  308. #endif DEBUG
  309.             if (fread(&info->header, sizeof(info->header), 1, file) != 1) {
  310. #ifdef PARANOID
  311.                 iff_truncated(2);
  312. #endif PARANOID
  313.                 return NULL;
  314.             }
  315.             got_header = TRUE;
  316.             break;
  317.         case CMAP:
  318. #ifdef DEBUG
  319.             printf("\tCMAP %ld\n", chunk.iff_length);
  320. #endif DEBUG
  321.             if (!got_header) {
  322. #ifdef PARANOID
  323.                 printf("CMAP befor BMHD\n");
  324. #endif PARANOID
  325.                 return NULL;
  326.             }
  327.             if (chunk.iff_length <= 3*MAXCOL ) {
  328.                 if (fread(info->cmap, (int)chunk.iff_length, 1, file) != 1) {
  329. #ifdef PARANOID
  330.                     iff_truncated(3);
  331. #endif PARANOID
  332.                     return NULL;
  333.                 }
  334.             } else {
  335. #ifdef PARANOID
  336.                 printf("warning, more than %d colors in ILBM CMAP\n",
  337.                     MAXCOL);
  338. #endif PARANOID
  339.                 if (fread(info->cmap, (int) 3*MAXCOL, 1, file) != 1) {
  340. #ifdef PARANOID
  341.                     iff_truncated(4);
  342. #endif PARANOID
  343.                     return NULL;
  344.                 }
  345.                 bit_bucket(file, chunk.iff_length - 3*MAXCOL);
  346.             }
  347.             got_cmap = TRUE;
  348.             if (just_colors)
  349.                 return info;
  350.             break;
  351.         case BODY:
  352.             if (!got_cmap) {
  353. #ifdef PARANOID
  354.                 printf("BODY before CMAP\n");
  355. #endif PARANOID
  356.                 return NULL;
  357.             }
  358. #ifdef DEBUG
  359.             printf("\tBODY %ld\n", chunk.iff_length);
  360. #endif DEBUG
  361.             return read_body(file, info, chunk.iff_length);
  362.  
  363.         default:    /* Squawk about unknown types if PARANOID */
  364. #ifdef PARANOID
  365.             printf("\t unknown type %lx of b4_type\n", chunk.iff_type.b4_type);
  366.         case GRAB:  /* Ignore documented but unwanted types */
  367.         case DEST:
  368.         case SPRT:
  369.         case CAMG:
  370.         case CRNG:
  371.         case CCRT:
  372. #endif PARANOID
  373.             bit_bucket(file, chunk.iff_length);
  374.             break;
  375.         }
  376.         read_in += EVEN(chunk.iff_length) + sizeof(chunk);
  377.     }
  378. #ifdef PARANOID
  379.     printf("no BODY in ILBM\n");
  380. #endif PARANOID
  381.     return NULL; 
  382. }
  383.  
  384.  
  385.  
  386. STATIC struct ILBM_info *read_body(file, info, length)
  387. FILE *file;
  388. register struct ILBM_info *info;
  389. long length;
  390. {
  391.     struct ILBM_header *header;
  392.     struct BitMap *bm;
  393.     int i, j;
  394.     int rlength;
  395.     int plane_offset;
  396. #ifdef MANDEL
  397.     int YSize, DestY = 0;
  398. #endif
  399.  
  400. #ifdef DEBUG
  401.     printf("read_body( %lx %lx %ld)\n", file, info, length);
  402. #endif DEBUG
  403.  
  404. #ifdef PARANOID
  405. /* When paranoid do a little error checking first ... fail fast! */
  406.     if (info->header.nPlanes > 8) {
  407.         printf("Whoa, woe  Dale only speaks 8 planes boy, not %d\n",
  408.         info->header.nPlanes);
  409.         return NULL;
  410.     }
  411. #endif PARANOID
  412.  
  413. /* Ok a little more error checking */
  414.     if (info->header.compression != 0 && info->header.compression != 1) {
  415. #ifdef PARANOID
  416.         printf("unrecognized compression type %d\n", info->header.compression);
  417. #endif PARANOID
  418.         return NULL;
  419.     }
  420.  
  421. /* Set up the bitmap part that doesn't involve memory allocation first -
  422.    hey this part does get done, and let's be optimistic...*/
  423.     info->bitmap.BytesPerRow = line_bytes(info->header.w);
  424.     info->bitmap.Rows = info->header.h;
  425.     info->bitmap.Depth = info->header.nPlanes;
  426.     info->bitmap.Flags = info->bitmap.pad = 0;
  427.  
  428.     rlength = info->bitmap.Rows * info->bitmap.BytesPerRow;
  429.  
  430.     for (i=0; i<info->header.nPlanes; i++) {
  431.         if ((info->bitmap.Planes[i] = ralloc(rlength)) == NULL) {
  432. #ifdef PARANOID
  433.             printf("couldn't alloc plane %d in read_body\n",i);
  434. #endif PARANOID
  435.             free_planes( &info->bitmap );
  436.             return NULL;
  437.         }
  438.     }
  439.  
  440.     plane_offset = 0;
  441. #ifdef MANDEL
  442.     YSize = (MAXPLANESIZE / info->bitmap.BytesPerRow);
  443. #endif MANDEL
  444.     for (i=0; i<info->bitmap.Rows; i++) {
  445.     /* This test should be in the inner loop for shortest code,            */
  446.     /* in the outer loop for greatest speed, so sue me I compromised    */
  447.         if (info->header.compression == 0) {
  448.             for (j = 0; j < info->bitmap.Depth; j++) {
  449.                 if ( fread(info->bitmap.Planes[j] + plane_offset,
  450.                     info->bitmap.BytesPerRow, 1, file) != 1) {
  451. #ifdef PARANOID
  452.                     iff_truncated(6);
  453. #endif PARANOID
  454.                     free_planes( &info->bitmap);
  455.                     return NULL;
  456.                 }
  457.             }
  458.         } else {
  459.             register char *dest, value;
  460.             register int so_far, count;  /* How much have unpacked so far */
  461.  
  462.             for (j = 0; j < info->bitmap.Depth; j++) {
  463.                 so_far = info->bitmap.BytesPerRow;
  464.                 dest = (char *)info->bitmap.Planes[j] + plane_offset;
  465.                 while (so_far > 0) {
  466.                     if ( (value = getc(file)) == 128) {
  467. #ifdef DEBUG
  468.                         printf("NOP\n");
  469. #endif DEBUG
  470.                     } else if (value > 0) {
  471.                         count = (int)value + 1;
  472.                         so_far -= count;
  473.                         if ( fread(dest, count, 1, file) != 1) {
  474. #ifdef PARANOID
  475.                             iff_truncated(7);
  476. #endif PARANOID
  477.                             free_planes( &info->bitmap);
  478.                             return NULL;
  479.                         }
  480.                         dest += count;
  481.                     } else  {
  482.                         count = (int)-value + 1;
  483.                         so_far -= count;
  484.                         value = getc(file);
  485.                         while (--count >= 0)  /* This is fastest loop on the 68000 */
  486.                             *dest++ = value;
  487.                     }
  488.                 }
  489.                 if (so_far != 0) {
  490. #ifdef PARANOID
  491.                     printf("compression quite screwed up, aborting %d\n", so_far);
  492. #endif PARANOID
  493.                     free_planes( &info->bitmap);
  494.                     return NULL;
  495.                 }
  496.             }
  497.         }
  498.         plane_offset += info->bitmap.BytesPerRow;
  499. #ifdef MANDEL
  500.         if (plane_offset > MAXPLANESIZE - info->bitmap.BytesPerRow) {
  501.             BltBitMapRastPort(&info->bitmap, 0L, 0L, MainWindow->RPort,
  502.                 0L, (long) DestY, info->bitmap.BytesPerRow * 8L,
  503.                 (long) YSize, COPY_MINTERM);
  504.             plane_offset = 0;
  505.             DestY += YSize;
  506.         }
  507. #endif MANDEL
  508.     }
  509. #ifdef MANDEL
  510.     if (plane_offset) {
  511.         BltBitMapRastPort(&info->bitmap, 0L, 0L, MainWindow->RPort,
  512.             0L, (long) DestY, info->bitmap.BytesPerRow * 8L,
  513.             (long) plane_offset / info->bitmap.BytesPerRow, COPY_MINTERM);
  514.     }
  515. #endif MANDEL
  516.  
  517.     if (length & 1) {
  518.         /* Skip padding byte */
  519.         getc(file);
  520.     }
  521.  
  522.     return info;
  523. }
  524.  
  525.  
  526. void free_planes(bmap)
  527. register struct BitMap *bmap;
  528. {
  529.     PLANEPTR plane;
  530.     long length;
  531.     short i;
  532.  
  533.     length = bmap->BytesPerRow * bmap->Rows;
  534.  
  535.     for (i=0; i<8; i++)
  536.         if ( (plane = bmap->Planes[i]) != NULL)
  537.             rfree(plane, length);
  538. }
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545. #undef DEBUG
  546. #undef PARANOID
  547.  
  548. /*----------------------------------------------------------------------*
  549.  * jpacker.c Convert data to "cmpByteRun1" run compression.  
  550.  *
  551.  * pack_row() is an adaptation of PackRow() 
  552.  * by Jerry Morrison and Steve Shaw, Electronic Arts,
  553.  * modified and tweaked by Jim Kent, Dancing Flame 05/02/86
  554.  *
  555.  *    control bytes:
  556.  *     [0..127]   : followed by n+1 bytes of data.
  557.  *     [-1..-127] : followed by byte to be repeated(-n)+1 times.
  558.  *     -128       : NOOP.
  559.  *
  560.  *
  561.  * write_iff() is the only function you can access in this module.
  562.  *----------------------------------------------------------------------*/
  563.  
  564. /*
  565.     #include <exec/types.h>
  566.     #include <graphics/gfx.h>
  567.     #include <stdio.h>
  568.     #include "jiff.h"
  569. */
  570.  
  571. #define DUMP    0
  572. #define RUN    1
  573.  
  574. #define MINRUN 3    
  575. #define MAXRUN 128
  576. #define MAXDAT 128
  577.  
  578. /* pack_row - pass source line pointer, length of line, and file.
  579.    Returns # of bytes after compression.  Returns 0 on write error.
  580.    Pass file = NULL to just find out length, 
  581.    otherwise will write compressed row to file. */
  582. STATIC unsigned int pack_row(file, source, size)
  583. FILE *file;
  584. char *source;
  585. int size;
  586. {
  587.     char    c,
  588.     lastc = '\0';
  589.     short mode = DUMP;
  590.     short   nbuf = 0;        /* Number of chars in buffer */
  591.     short   rstart = 0;        /* Buffer index current run starts */
  592.     unsigned short putsize;
  593.     char    buf[MAXDAT*3/2];        /* I think MAXDAT+1 would suffice */
  594.  
  595.     putsize = 0;
  596.     buf[0] = lastc = *source++;/* So have valid lastc */
  597.     nbuf = 1;
  598.     size--;            /* Since one byte eaten. */
  599.  
  600.  
  601.     for (; size; --size) {
  602.         buf[nbuf++] = c = *source++;
  603.         switch (mode) {
  604.         case DUMP: 
  605.             /* If the buffer is full, write the length byte, then the data */
  606.             if (nbuf > MAXDAT) {
  607.                 if (file != NULL) {
  608.                     if (putc(nbuf-2, file) == EOF)
  609.                         return 0;
  610.                     if (fwrite(buf, nbuf-1, 1, file) != 1)
  611.                         return 0;
  612.                 }
  613.                 putsize += nbuf;
  614.                 buf[0] = c;
  615.                 nbuf = 1;
  616.                 rstart = 0;
  617.                 break;
  618.             }
  619.  
  620.             if (c == lastc) {
  621.                 if (nbuf - rstart >= MINRUN) {
  622.                     if (rstart > 0) {
  623.                         if (file != NULL) {
  624.                             if (putc(rstart-1, file) == EOF)
  625.                                 return 0;
  626.                             if (fwrite(buf, rstart, 1, file) != 1)
  627.                                 return 0;
  628.                         }
  629.                         putsize += rstart+1;
  630.                     }
  631.                     mode = RUN;
  632.                 }
  633.                 else if (rstart == 0)
  634.                     mode = RUN;
  635.             /* No dump in progress, so can't lose by making these 2 a run. */
  636.             }
  637.             else
  638.                 rstart = nbuf - 1;/* First of run */
  639.             break;
  640.  
  641.         case RUN: 
  642.             if ((c != lastc) ||(nbuf - rstart > MAXRUN)) {
  643.                 /* Output run */
  644.                 if (file != NULL) {
  645.                     if (putc( -(nbuf - rstart - 2), file) == EOF)
  646.                         return 0;
  647.                     if (putc( lastc, file) == EOF)
  648.                         return 0;
  649.                 }
  650.                 putsize += 2;
  651.                 buf[0] = c;
  652.                 nbuf = 1;
  653.                 rstart = 0;
  654.                 mode = DUMP;
  655.             }
  656.             break;
  657.         }
  658.  
  659.         lastc = c;
  660.     }
  661.  
  662.     switch (mode) {
  663.     case DUMP: 
  664.         if (file != NULL) {
  665.             if (putc(nbuf-1, file) == EOF)
  666.                 return 0;
  667.             if (fwrite(buf, nbuf, 1, file) != 1)
  668.                 return 0;
  669.         }
  670.         putsize += nbuf+1;
  671.         break;
  672.     case RUN: 
  673.         if (file != NULL) {
  674.             if (putc( -(nbuf - rstart - 1), file) == EOF)
  675.                 return 0;
  676.             if (putc( lastc, file) == EOF)
  677.                 return 0;
  678.         }
  679.         putsize += 2;
  680.         break;
  681.     }
  682.     return putsize;
  683. }
  684.  
  685.  
  686. STATIC unsigned long pack_bitmap(file, bm)
  687. FILE *file;
  688. struct BitMap *bm;
  689. {
  690.     unsigned short i, j;
  691.     unsigned row_length;
  692.     unsigned long compressed_length;
  693.     unsigned plane_offset;
  694.  
  695. #ifdef DEBUG
  696.     printf("pack_bitmap( %lx %lx)\n", file, bm);
  697. #endif DEBUG
  698.  
  699. #ifdef PARANOID
  700. /* When paranoid do a little error checking first ... Fail fast! */
  701.     if (bm->BytesPerRow <= 0 || bm->Rows <= 0 || bm->BytesPerRow > MAXDAT) {
  702.         printf("bitmap %d bytes by %d rows?????\n", bm->BytesPerRow,
  703.         bm->Rows);
  704.         return 0;
  705.     }
  706.     if (bm->Depth <= 0 || bm->Depth > 8) {
  707.         printf("bitmap with %d planes ??????\n", bm->Depth);
  708.         return 0;
  709.     }
  710. #endif PARANOID
  711.  
  712.     compressed_length = 0;
  713.     plane_offset = 0;
  714.     for (i=0; i<bm->Rows; i++) {
  715.         for (j = 0; j < bm->Depth; j++) {
  716.             if ( (row_length = pack_row(file, bm->Planes[j] + plane_offset, 
  717.             bm->BytesPerRow)) == 0) {
  718. #ifdef PARANOID
  719.                 printf("error packing row %d plane %d\n", i, j);
  720. #endif PARANOID
  721.                 return 0;
  722.             }
  723.             compressed_length += row_length;
  724.         }
  725.         plane_offset += bm->BytesPerRow;
  726.     }
  727.     if ( compressed_length & 1) {  /* Check to see odd length */
  728.         if (file != NULL) {
  729.             if ( putc( 0, file) == EOF) {
  730.                 return 0;
  731.             }
  732.         }
  733.         /* compressed_length++; Deleted!!! Padding should NOT be included */
  734.         /* in the chunk size !!! */
  735.     }
  736.     return compressed_length;
  737. }
  738.  
  739. int write_iff(name, colors, bits, xoff, yoff, width, compressed, ExtraSize, ExtraInfo)
  740. char *name;
  741. unsigned char *colors;
  742. register struct BitMap *bits;
  743. short xoff, yoff;
  744. short compressed;
  745. int ExtraSize;
  746. APTR ExtraInfo;
  747. {
  748.     FILE *file;
  749.     struct form_chunk chunk;
  750.     struct iff_chunk ichunk;
  751.     struct BitMapHeader header;
  752.     long bits_size;
  753.     short i;
  754.     register short j;
  755.     register short row_offset;
  756.  
  757.     if ((file = fopen(name, "w") ) == 0) {
  758. #ifdef PARANOID
  759.         printf("couldn't Open %s to write\n", name);
  760. #endif PARANOID
  761.         goto abort;
  762.     }
  763.  
  764.     /* Say its a FORM ILBM */
  765.     chunk.fc_type.b4_type = FORM;
  766.     chunk.fc_subtype.b4_type = ILBM;
  767. #ifdef MANDEL
  768.     chunk.fc_length = 4 + 3*sizeof(struct iff_chunk) + MAXCOL*3 + 
  769.         sizeof(struct BitMapHeader) + ExtraSize;
  770. #else
  771.     chunk.fc_length = 4 + 3*sizeof(struct iff_chunk) + MAXCOL*3 + 
  772.         sizeof(struct BitMapHeader);
  773. #endif MANDEL
  774.     if (bits) {
  775.         if (compressed) {
  776.             if ( (bits_size = pack_bitmap(NULL, bits)) == 0)
  777.                 goto abort;
  778.         } else {
  779.             bits_size =  bits->BytesPerRow*bits->Rows*bits->Depth;
  780.         }
  781.         chunk.fc_length += bits_size;
  782.         if (bits_size & 1)    chunk.fc_length++;
  783.     }
  784.     if (fwrite(&chunk, sizeof(chunk), 1, file) != 1)
  785.         goto abort;
  786.  
  787. /* Here comes a BitMapHeader */
  788.     ichunk.iff_type.b4_type = BMHD;
  789.     ichunk.iff_length = sizeof(header);
  790.     if (fwrite(&ichunk, sizeof(ichunk), 1, file) != 1)
  791.         goto abort;
  792.  
  793. /* Initialize the BitMapHeader to normal values */
  794.     header.masking = 0;
  795.     header.pad1 = 0;
  796.     header.transparentColor = 0;
  797.     if (compressed)
  798.         header.compression = 1;
  799.     else
  800.         header.compression = 0;
  801.     header.pageWidth = width;
  802.     header.pageHeight = bits? bits->Rows: YMAX;
  803.     header.xAspect = width > LOXMAX? XASPECT: XASPECT*2;
  804.     header.yAspect = YASPECT;
  805. /* If it's not just a color map give the dimensions of rasters */
  806.     if (bits) {
  807.         header.w = width;
  808.         header.h = bits->Rows;
  809.         header.nPlanes = bits->Depth;
  810.         header.x = xoff;
  811.         header.y = yoff;
  812.     }
  813.     if (fwrite(&header, sizeof(header), 1, file) != 1)
  814.         goto abort;
  815.  
  816. /* Squirt out the color map */
  817.     ichunk.iff_type.b4_type = CMAP;
  818.     ichunk.iff_length = MAXCOL*3;
  819.     if (fwrite(&ichunk, sizeof(ichunk), 1, file) != 1)
  820.         goto abort;
  821.     if (fwrite(colors, (int) 3*MAXCOL, 1, file) != 1)
  822.         goto abort;
  823.  
  824. /* If they be bits then squirt out the bits */
  825.     if (bits) {
  826.         ichunk.iff_type.b4_type = BODY;
  827.         ichunk.iff_length = bits_size;
  828.         if (fwrite(&ichunk, sizeof(ichunk), 1, file) != 1)
  829.             goto abort;
  830.         if (compressed) {
  831.             if (pack_bitmap(file, bits) == 0)
  832.                 goto abort;
  833.         } else {
  834.             i = bits->Rows;
  835.             row_offset = 0;
  836.             while (--i >= 0) {
  837.                 for (j=0; j<bits->Depth; j++) {
  838.                     if (fwrite( bits->Planes[j]+row_offset,
  839.                         bits->BytesPerRow, 1, file) != 1)
  840.                         goto abort;
  841.                 }
  842.                 row_offset += bits->BytesPerRow;
  843.             }
  844.         }
  845.     }
  846.  
  847. #ifdef MANDEL
  848.     if (ExtraSize) {
  849.         /* We want to tack on an extra MAND */
  850.         if (fwrite(ExtraInfo, ExtraSize, 1, file) != 1) goto abort;
  851.     }
  852. #endif MANDEL
  853.  
  854.     fclose(file);
  855.  
  856.     return 1;
  857. abort:
  858.     fclose(file);
  859.     return 0;
  860. }
  861.  
  862.  
  863. /***********************************************************************
  864. * put_ea_cmap given an ea-type color map:
  865. * an array of unsigned chars of form ea_cmap[] = {r, g, b, r, g, b...}
  866. * turn it into an amiga-type color map:
  867. * an array of unsigned short of form amiga_cmap = {0xrgb, 0xrgb, ...}
  868. * and then tell Dale this is the colors we want for our viewport
  869. */
  870. void put_ea_cmap(ea_cmap, colors, Screen)
  871. unsigned char *ea_cmap;
  872. int colors;
  873. struct Screen *Screen;
  874. {
  875.     unsigned short amy_cmap[MAXCOL];
  876.     register int i;
  877.     register short color;
  878.  
  879.     if (colors > MAXCOL)   /* Color clipping */
  880.         colors = MAXCOL;
  881.     for (i=0; i<colors; i++) {
  882.         color  = (*ea_cmap++ & 0xF0) << 4;
  883.         color |=  *ea_cmap++ & 0xF0;
  884.         color |= (*ea_cmap++ & 0xF0) >> 4;
  885.         amy_cmap[i] = color;
  886.     }
  887.     LoadRGB4( &Screen->ViewPort, amy_cmap, (long)colors);
  888. }
  889.  
  890. void get_ea_cmap(ea_cmap, colors, Screen)
  891. unsigned char *ea_cmap;
  892. int colors;
  893. struct Screen *Screen;
  894. {
  895.     register long i;
  896.     register unsigned short rgb;
  897.  
  898.     if (colors > MAXCOL)   /* Color clipping */
  899.         colors = MAXCOL;
  900.     for (i=0; i<colors; i++) {
  901.         rgb = GetRGB4(Screen->ViewPort.ColorMap, i);
  902.         *ea_cmap++ = (rgb & 0xF00) >> 4;
  903.         *ea_cmap++ = (rgb & 0x0F0);
  904.         *ea_cmap++ = (rgb & 0x00F) << 4;
  905.     }
  906. }
  907.